package cooperated

import (
	"bytes"
	"fmt"
	"strings"

	"gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/common/feature/orbit/chess_protocol"
	"gddgame.cc/galaxy/common/namespaces/cooperate"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/project/breeder/breeder/center"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
)

type TypeMapData interface {
	DefaultMap() string
	GetAccount(accountId int) *model.User
	GetUnit(userUnitId string) *model.UserUnit
}

type TypeManager struct {
	*center.Center
	TypeMapData
	cooperate.MapCenter

	Event *EventMap

	Health      int
	MoveLock    int
	AttackLock  int
	Safe        int
	SpeedChange int

	AttackDistance    int
	AttackSpeed       int
	Speed             int
	View              int
	SearchDistance    int
	DefendDistance    int
	FollowDistance    int
	CanTeleportIn     int
	AttackSpeedChange int

	HoldTime    int
	DestroyTime int
}

func NewTypeManager() *TypeManager {
	st := &TypeManager{}

	return st
}

func (logic *TypeManager) ChangeCenter(center *center.Center) {
	logic.Center = center

	// 保存属性id
	logic.Health = logic.AttrData.KeyToId("allHealth")
	logic.MoveLock = logic.AttrData.KeyToId("moveLock")
	logic.AttackLock = logic.AttrData.KeyToId("attackLock")
	logic.Safe = logic.AttrData.KeyToId("safe")
	logic.SpeedChange = logic.AttrData.KeyToId("speedChange")

	logic.AttackSpeed = logic.AttrData.KeyToId("attackSpeed")
	logic.AttackDistance = logic.AttrData.KeyToId("attackDistance")
	logic.Speed = logic.AttrData.KeyToId("speed")
	logic.View = logic.AttrData.KeyToId("view")
	logic.AttackSpeedChange = logic.AttrData.KeyToId("attackSpeedChange")
	logic.SearchDistance = logic.AttrData.KeyToId("searchDistance")
	logic.DefendDistance = logic.AttrData.KeyToId("defendDistance")
	logic.FollowDistance = logic.AttrData.KeyToId("followDistance")
	logic.CanTeleportIn = logic.AttrData.KeyToId("canTeleportIn")

	// 将自定义sync计入自定义常量
	for key, _ := range PersistenceMap {
		logic.Center.PersistenceMap[key] = true
	}
	logic.Center.GetConfig("HoldTime", &logic.HoldTime)
	logic.Center.GetConfig("DestroyTime", &logic.DestroyTime)
}

//
func (logic *TypeManager) BindData(data TypeMapData) {
	logic.TypeMapData = data
}
func (logic *TypeManager) Register(dm *cooperate.DataManager) {
	dm.DataTypeFieldsDefineMap = DataTypeFieldMap

	dm.ExtendModeMap = ExtendModeMap
	dm.PersistenceMap = logic.Center.PersistenceMap
	dm.SyncDefineList = logic.Center.SyncDefineList

	dm.IdentityList = IdentityList
}

func (logic *TypeManager) InitOperate(center cooperate.MapCenter) {
	logic.MapCenter = center

	logic.Event = NewEventMap(center, logic.Center.SettingMessageMap)
}

func (logic *TypeManager) LoadData(mapInstance cooperate.MapProxy, data structure.Data, items []cooperate.BaseItem, allMap map[string][]interface{}, sync bool) ([]cooperate.BaseItem, map[string][]interface{}) {
	//Accounts := logic.GetList(conn, mapNoId, data, AccountType)
	Units := logic.GetList(mapInstance.GetMapNoId(), data, logic.DefaultBeDepend(data.GetDataType(), UnitDataType))
	Builds := logic.GetList(mapInstance.GetMapNoId(), data, logic.DefaultBeDepend(data.GetDataType(), BuildDataType))
	Items := logic.GetList(mapInstance.GetMapNoId(), data, logic.DefaultBeDepend(data.GetDataType(), ItemDataType))
	Nodes := logic.GetList(mapInstance.GetMapNoId(), data, logic.DefaultBeDepend(data.GetDataType(), NodeDataType))
	PathNodes := logic.GetList(mapInstance.GetMapNoId(), data, logic.DefaultBeDepend(data.GetDataType(), PathNodeDataType))
	for _, id := range Builds {
		iid := id.(cooperate.MapNode)
		v := logic.GetDetailCache(mapInstance, structure.NewBaseData(BuildType, iid.Position))
		if v == nil {
			continue
		}
		build := v.(*Build)
		ps, item := mapInstance.TransformLoad(BuildType, v, nil)
		logic.TransformMap(allMap, ps, item)
		mapInstance.OnUpdateData(build, sync)
		items = append(items, build)
	}
	for _, id := range Units {
		v := logic.GetDetailCache(mapInstance, structure.NewBaseData(UnitType, id))
		if v == nil {
			continue
		}
		unit := v.(*Unit)
		//fmt.Println("unit", mapInstance, unit.Id, unit.Ignore, unit.Position, unit.MoveProp.Status, unit.DoSustain)
		if unit.Ignore {
			continue
		}
		if unit.Position == nil || len(unit.Position) == 0 {
			continue
		}
		ps, item := mapInstance.TransformLoad(UnitType, v, nil)
		logic.TransformMap(allMap, ps, item)
		mapInstance.OnUpdateData(unit, sync)
		items = append(items, unit)
	}
	for _, id := range Items {
		v := logic.GetDetailCache(mapInstance, structure.NewBaseData(ItemType, id))
		//fmt.Println("item", id, v)
		if v == nil {
			continue
		}
		iItem := v.(*Item)
		ps, item := mapInstance.TransformLoad(ItemType, v, nil)
		logic.TransformMap(allMap, ps, item)
		mapInstance.OnUpdateData(iItem, sync)
		items = append(items, iItem)
	}
	for _, id := range Nodes {
		iid := id.(cooperate.MapNode)
		v := logic.GetDetailCache(mapInstance, structure.NewBaseData(NodeType, iid.Position))
		//fmt.Println("node", id, v)
		if v == nil {
			continue
		}
		node := v.(*Node)
		//fmt.Println(node.Key, node.Position)
		ps, item := mapInstance.TransformLoad(NodeType, v, nil)
		logic.TransformMap(allMap, ps, item)
		mapInstance.OnUpdateData(node, sync)
		items = append(items, node)
	}
	for _, id := range PathNodes {
		iid := id.(cooperate.MapNode)
		v := logic.GetDetailCache(mapInstance, structure.NewBaseData(PathNodeType, iid.Position))
		//fmt.Println("node", id, v)
		if v == nil {
			continue
		}
		node := v.(*Node)
		mapInstance.TransformLoad(PathNodeType, v, nil)
		//instance.TransformMap(allMap, ps, item)
		mapInstance.OnUpdateData(node, sync)
		items = append(items, node)
	}
	return items, allMap
}

func (logic *TypeManager) OnOperateBefore(mapInstance cooperate.MapProxy, instance cooperate.PropsInstance, fd *cooperate.FieldsDefine, from structure.Data, operate *cooperate.UpdateOperateContent) bool {
	// 特殊key不进入redis
	// buff或者指令根据配置得到是否要持久化
	// 对于持久化需要返回true
	switch operate.Operate {
	case cooperate.ChangeData:
		switch operate.Key {
		case Plan:
			fallthrough
		case Positions:
			fallthrough
		case Listen:
			// 坐标需要转城[]byte，读取时也需要转换
			//fmt.Println("positions", target, operate.Value)
			p := cooperate.NewPositionsBy(operate.Value)
			operate.Value = (&p).Bytes()
		case AttackTarget:
			// nil就是取消攻击目标
			p := structure.NewBaseDataBy(operate.Value)
			if p != nil {
				operate.Value = p.Bytes()
			}
		case AttrAbility:
			p := game.NewIntAbilitySliceBy(operate.Value)
			operate.Value = (&p).Bytes()
		case BuffAbility:
			p := game.NewInfAbilitySliceBy(operate.Value)
			operate.Value = (&p).Bytes()
		case DirectIds:
			p := game.NewIntAbilitySliceBy(operate.Value)
			operate.Value = (&p).Bytes()
		case DoSustain:
			p := cooperate.NewSustainBy(operate.Value)
			if p != nil {
				operate.Value = p.Bytes()
			}
		case UnitStatus:
			p := cooperate.NewSustainBy(operate.Value)
			if p != nil {
				operate.Value = p.Bytes()
			}
		default:
			if instance != nil && instance.Timer() != nil {
				prefix := strings.HasPrefix(operate.Key, DirectCoolPrefix)
				if prefix {
					directId := instance.Timer().Id(DirectCoolPrefix, operate.Key)
					// 根据后台设置，是否持久化冷却时间
					//fmt.Println("direct", operate.Key, directId)
					direct := logic.Center.DirectMap[directId]
					if direct != nil {
						return direct.CoolSave
					}
				}
			}

		}
	case cooperate.AddTimeSorted:
		if operate.Key == string(BuffAbilityExtend) {
			buffInfo := NewBuffInfoBy(utils.ToBytes(operate.Value), operate.Index)
			buff := logic.Center.BuffMap[buffInfo.BuffId]
			if buff != nil {
				return buff.IsSave
			}
		}
	case cooperate.RemoveTimeSorted:
		if operate.Key == string(BuffAbilityExtend) {
			buffInfo := NewBuffInfoBy(utils.ToBytes(operate.Value), operate.Index)
			buff := logic.Center.BuffMap[buffInfo.BuffId]
			if buff != nil {
				return buff.IsSave
			}
		}
	case cooperate.BindEvent:
		return true
	case cooperate.ClearEvent:
		return true
	case cooperate.ChangeDataSync:
		fallthrough
	case cooperate.IncrDataSync:
		fallthrough
	case cooperate.ChangeDataLesserSync:
		fallthrough
	case cooperate.ChangeDataGreaterSync:
		return true
	}
	return false
}

func (logic *TypeManager) OnOperateAfter(mapInstance cooperate.MapProxy, instance cooperate.PropsInstance, fd *cooperate.FieldsDefine, from structure.Data, operate *cooperate.UpdateOperateContent) {
	if operate.Value == nil {
		return
	}
	//if operate.Key == string(DataExtend) {
	//	fmt.Println("operate", from, target, operate.Key, operate.Operate, operate.Index, operate.Value)
	//}
	if instance != nil {
		dm := logic.GetDefineMap(instance.GetDataType(), instance.ToString(Key))
		if dm != nil && len(dm) > 0 {
			//fmt.Println("oprea", dm, operate.Key, dm[operate.Key], operate.Value)
			if ii, ok := dm[operate.Key]; ok {
				// 将后台设定不同种类，转移到extend模式，基本都是changeData->changeList
				operate.Operate = cooperate.ChangeList
				operate.Key = string(DefineExtend)
				operate.Index = ii
			}
		}
	}

	switch operate.Operate {
	//case cooperate.ChangePosition:
	//fmt.Println(operate.Value)
	case cooperate.ChangeData:
		switch operate.Key {
		case AttrAbility:
			p := game.NewIntAbilitySliceBy(operate.Value)
			abilityProp := ReceiveAbilityProp(instance)
			if abilityProp == nil {
				attrMap := p.ListToMap()
				operate.Props = logic.Center.DiffAttr(attrMap)

				//fmt.Println("diff info", operate.Props, attrMap)
				return
			}
			diffMap := abilityProp.ChangeAttr(p)
			operate.Props = diffMap
			//fmt.Println("diff", diffMap)
		case BuffAbility:
			abilityProp := ReceiveAbilityProp(instance)
			if abilityProp == nil {
				return
			}
		}
	case cooperate.IncrDataGreaterSync:
		switch operate.Key {
		case Health:
			if utils.ToInt(operate.Value) <= 0 && instance != nil {
				//fmt.Println("destroy", operate, from, instance.BaseData())
				// 创建击杀
				mapInstance.OnEvent(OnDestroyEvent, []interface{}{from, instance})
			}
		default:
		}
	case cooperate.AddTimeSorted:
		if operate.Key == string(BuffAbilityExtend) {
			// 添加buff，分析buff影响范围，
			abilityProp := ReceiveAbilityProp(instance)
			if abilityProp == nil {
				return
			}
			buffInfo := NewBuffInfoBy(utils.ToBytes(operate.Value), operate.Index)
			diffMap := abilityProp.AddBuff(buffInfo)
			operate.Props = diffMap

			instance.ClearTimeSorted(logic, BuffAbilityExtend, abilityProp.BuffInfoSlice, abilityProp.lastClearBuffSecond, 300)
			abilityProp.lastClearBuffSecond = logic.CurrentSecond()
		}
	case cooperate.RemoveTimeSorted:
		if operate.Key == string(BuffAbilityExtend) {
			// 移除buff，获取当前buff对应time，才能移除同步服务器上的数据
			abilityProp := ReceiveAbilityProp(instance)
			if abilityProp == nil {
				fmt.Println("ability props miss")
				return
			}
			buffInfo := NewBuffInfoBy(utils.ToBytes(operate.Value), 0)
			diffMap, pass := abilityProp.RemoveBuff(buffInfo, operate.Index, operate.PassValue)
			//fmt.Println("remove time sorted", operate.Index, diffMap, pass)
			operate.Props = diffMap
			operate.Index = buffInfo.Time
			operate.PassValue = pass

			instance.ClearTimeSorted(logic, BuffAbilityExtend, abilityProp.BuffInfoSlice, abilityProp.lastClearBuffSecond, 300)
			abilityProp.lastClearBuffSecond = logic.CurrentSecond()
		}
	}
	switch operate.Operate {
	case cooperate.IncrDataSync:
		fallthrough
	case cooperate.ChangeDataGreaterSync:
		fallthrough
	case cooperate.ChangeDataLesserSync:
		fallthrough
	case cooperate.ChangeDataSync:
		prefix := strings.HasPrefix(operate.Key, cooperate.StatKeyPrefix)
		//fmt.Println("change data sync", operate.Key, prefix, operate.SyncValue, operate.Value)
		if prefix {
			key := strings.TrimPrefix(operate.Key, cooperate.StatKeyPrefix)
			// value = new
			// syncValue = old
			logic.Center.UpdateStatNotice(mapInstance, instance, key, utils.ToInt(operate.SyncValue), utils.ToInt(operate.Value))
		}
	}
}

func (logic *TypeManager) GenerateAccount(accountId int, openId string, identity int) map[string]interface{} {
	// todo 不同的identity，初始position不同
	return map[string]interface{}{
		Id:       accountId,
		Open:     openId,
		Identity: identity,
		MapNoId:  logic.DefaultMap(),
	}
}

func (logic *TypeManager) UpdateProp(instance cooperate.PropsInstance, update *cooperate.UpdateContent) {
	//fmt.Println("update", instance.Data())
	fd, _ := DataTypeFieldMap[instance.GetDataType()]
	instance.Lock()
	if update.Props != nil {
		for _, prop := range update.Props {
			instance.MergeProp(prop.Key, prop.Value)
		}
	}
	if update.UpdatePublicData != nil && update.UpdatePublicData.Props != nil {
		for _, prop := range update.UpdatePublicData.Props {
			field := fd.NoticePropMap[prop.Key]
			instance.MergeProp(field, prop.Value)
		}
	}
	//fmt.Println("update dependents", instance.Data(), update.Dependents)
	if update.Dependents != nil {
		for _, dependent := range update.Dependents {
			// 设置管理节点
			instance.MergeProp(dependent.Key, dependent.Depend.Id)

			depend := logic.DefaultDepend(instance.GetDataType(), dependent.Key)
			instance.ChangeInherit(depend, fd, false)
		}
	}
	instance.Unlock()
	if update.Event != nil {
		instance.MergeEvents(update.Event)
	}
}
func (logic *TypeManager) UpdateDetail(mapInstance cooperate.MapProxy, instance cooperate.PropsInstance, update *cooperate.UpdateContent) *chess_protocol.UpdatePublicData {
	//fmt.Println("update", instance.Data())
	fd, _ := DataTypeFieldMap[instance.GetDataType()]
	content := update.UpdatePublicData

	if fd == nil {
		return content
	}
	if update.Props != nil {
		for _, prop := range update.Props {
			//fmt.Println("update detail", prop)
			ff, ok := fd.Map[prop.Key]
			var pt cooperate.PropType
			if !ok {
				// Ability中进行其他字段的冷却时间处理
				pt = AbilityPropType
			} else {
				pt = ff.PropType
			}
			updateInstance := instance.Receive(pt)
			if updateInstance == nil {
				continue
			}
			updateInstance.UpdateField(prop.Key, prop.Value, content)

			relyList := fd.RelyField[prop.Key]
			if relyList != nil {
				for _, rely := range relyList {
					updateInstance := instance.Receive(rely)
					if updateInstance == nil {
						continue
					}
					updateInstance.UpdateField(prop.Key, prop.Value, content)
				}
			}
		}
	}
	if content != nil {
		if content.Extend != nil {
			total := content.ParseExtend()
			for index, extend := range total {
				extendS := fd.NoticeExtendMap[index]
				updateInstance := instance.Receive(fd.Map[string(extendS.Extend)].PropType)
				if updateInstance == nil {
					continue
				}
				updateInstance.UpdateExtend(extendS.Extend, extend, content)
				relyList := fd.RelyField[string(extendS.Extend)]
				if relyList != nil {
					for _, rely := range relyList {
						updateInstance := instance.Receive(rely)
						if updateInstance == nil {
							continue
						}
						updateInstance.UpdateExtend(extendS.Extend, extend, content)
					}
				}
			}
		}
		if content.Props != nil {
			for _, prop := range content.Props {
				//fmt.Println("update prop", prop)
				field := fd.NoticePropMap[prop.Key]
				ff := fd.Map[field]
				pt := ff.PropType
				updateInstance := instance.Receive(pt)
				if updateInstance == nil {
					continue
				}
				updateInstance.UpdateField(field, prop.Value, content)

				relyList := fd.RelyField[field]
				if relyList != nil {
					for _, rely := range relyList {
						updateInstance := instance.Receive(rely)
						if updateInstance == nil {
							continue
						}
						updateInstance.UpdateField(field, prop.Value, content)
					}
				}
			}
		}
		if content.ListId != nil {
			for _, beDepend := range content.ListId {
				be := fd.BeDepends[beDepend.Key]
				//fmt.Println("depend", instance.Data(), beDepend.Key, be, beDepend.Value)
				list := instance.ListId(be)
				if beDepend.Logic {
					list, _ = utils.AddString(list, utils.ToString(beDepend.Value))
				} else {
					list, _ = utils.RemoveString(list, utils.ToString(beDepend.Value))
				}
				//fmt.Println("depend", instance.Data(), beDepend.Key, be, list)
				instance.SetListId(be, list)
			}
		}
		if content.ListNo != nil {
			for _, beDepend := range content.ListNo {
				be := fd.BeDepends[beDepend.Key]
				//fmt.Println("depend", instance.Data(), beDepend.Key, be, beDepend.Value)
				list := instance.ListNo(be)
				if beDepend.Logic {
					list, _ = utils.AddInt(list, utils.ToInt(beDepend.Value))
				} else {
					list, _ = utils.RemoveInt(list, utils.ToInt(beDepend.Value))
				}
				//fmt.Println("depend", instance.Data(), beDepend.Key, be, list)
				instance.SetListNo(be, list)
			}
		}
		if content.ListNode != nil {
			for _, ownNode := range content.ListNode {
				be := fd.BeDepends[ownNode.Key]
				list := instance.ListNode(be)
				flag := -1
				for index, info := range list {
					if info.MapNoId != mapInstance.GetMapNoId() {
						continue
					}
					if !bytes.Equal(info.Position, ownNode.Value) {
						continue
					}
					flag = index
				}
				if ownNode.Logic {
					if flag == -1 {
						list = append(list, cooperate.MapNode{MapNoId: mapInstance.GetMapNoId(), Position: ownNode.Value})
					}
				} else {
					if flag >= 0 {
						l := len(list)
						if flag == 0 {
							list = list[1:]
						} else if flag == l-1 {
							list = list[0:flag]
						} else {
							list = append(list[:flag], list[flag+1:]...)
						}
					}
				}
				//fmt.Println("ownnode", instance.Data(), ownNode.Key, be, list)
				instance.SetListNode(be, list)
			}
		}
	}

	if content != nil && (len(content.Props) > 0 || len(content.Extend) > 0 || content.Message != nil) {
		return content
	}
	return nil
}

func (logic *TypeManager) GetDetail(mapInstance cooperate.MapBase, instance *cooperate.PropInstance, extendMap map[structure.ExtendType]interface{}) cooperate.PropsInstance {
	//fmt.Println("detail:", instance.Data())
	//startTime := time.Now()
	var item cooperate.PropsInstance
	var abilityProp *AbilityProp

	fd := logic.GetFieldsDefine(instance.DataType)
	owner := cooperate.NewAbilityOwner()
	// 直接解析：方便内部使用，也保证解析性能
	switch instance.GetDataType() {
	case AccountType:
		abilityProp = NewAbilityProp(logic, mapInstance, instance, owner, extendMap)
		account := &Account{
			OpenProp:    NewOpenProp(AccountType, utils.ToInt(instance.GetId()), instance.ToString(Open)),
			AbilityProp: abilityProp,
			MapProp:     NewMapProp(instance),

			AllianceId:   instance.ToInt(AllianceDataType),
			PropInstance: instance,
		}
		item = account
	case NodeType:
		fallthrough
	case PathNodeType:
		instance.MergeProp(Position, utils.ToBytes(instance.GetId()))
		node := &Node{
			//	 utils.ToBytes(logic.RemoveMapId(mapNoId, NodeType, data.GetId()))
			NodeProp: NewNodeProp(instance),
			MapProp:  NewMapProp(instance),
			SyncProp: NewSyncProp(instance, extendMap),

			PropInstance: instance,
		}
		item = node
		//fmt.Println("node", node.Id, node.Position, node.Identity)
	case UnitType:
		abilityProp = NewAbilityProp(logic, mapInstance, instance, owner, extendMap)
		unit := &Unit{
			IdProp:      NewIdProp(instance),
			MapProp:     NewMapProp(instance),
			MoveProp:    NewMoveProp(instance, abilityProp),
			AbilityProp: abilityProp,
			BattleProp:  NewBattleProp(abilityProp, instance),
			SyncProp:    NewSyncProp(instance, extendMap),

			PropInstance: instance,
			Status:       cooperate.NewSustainBy(instance.GetProp(UnitStatus)),
		}
		fmt.Println("unit", unit.Id, unit.Status, instance.GetProp(UnitStatus))
		item = unit
	case BuildType:
		instance.MergeProp(Position, utils.ToBytes(instance.GetId()))
		abilityProp := NewAbilityProp(logic, mapInstance, instance, owner, extendMap)
		build := &Build{
			NodeProp:    NewNodeProp(instance),
			MapProp:     NewMapProp(instance),
			FixProp:     NewFixProp(instance),
			AbilityProp: abilityProp,
			BattleProp:  NewBattleProp(abilityProp, instance),
			SyncProp:    NewSyncProp(instance, extendMap),

			PropInstance: instance,
		}
		//fmt.Println("build", build.Id, build.Position, build.Identity)
		item = build
	case ItemType:
		abilityProp = NewAbilityProp(logic, mapInstance, instance, owner, extendMap)
		ii := &Item{
			IdProp:      NewIdProp(instance),
			MapProp:     NewMapProp(instance),
			FixProp:     NewFixProp(instance),
			AbilityProp: abilityProp,
			BattleProp:  NewBattleProp(abilityProp, instance),
			SyncProp:    NewSyncProp(instance, extendMap),

			PropInstance: instance,
		}
		item = ii
	case FortressType:
		instance.MergeProp(Position, utils.ToBytes(instance.GetId()))
		fortress := &Fortress{
			MapProp: NewMapProp(instance),

			PropInstance: instance,
		}
		item = fortress
	case RegionType:
		instance.MergeProp(Position, utils.ToBytes(instance.GetId()))
		region := &Region{
			MapProp: NewMapProp(instance),

			PropInstance: instance,
		}
		item = region
	default:
		item = instance
	}
	//endTime := time.Now().Sub(startTime)
	//if endTime > 10*time.Millisecond {
	//	fmt.Println("detail load", endTime)
	//}
	//fmt.Println("detail", instance.Data())
	if fd != nil {
		for _, be := range fd.BeDepends {
			if be.DependIsPosition {
				list := logic.GetList(mapInstance.GetMapNoId(), instance, be)
				rr := make([]cooperate.MapNode, len(list))
				for index, info := range list {
					rr[index] = info.(cooperate.MapNode)
				}
				item.SetListNode(be, rr)
				//fmt.Println("ownnode", instance.Data(), be, list)
			} else if be.DependIsNo {
				list := utils.ToIntSlice(logic.GetList(mapInstance.GetMapNoId(), instance, be))
				item.SetListNo(be, list)
				//fmt.Println("depend", instance.Data(), be, list)
			} else if be.DependIsId {
				list := utils.ToStringSlice(logic.GetList(mapInstance.GetMapNoId(), instance, be))
				item.SetListId(be, list)
				//fmt.Println("depend", instance.Data(), be, list)
			}
		}
	}

	return item
}

func (logic *TypeManager) JudgeIdentity(selfIdentity int, targetIdentity int) (partner bool, enemy bool) {
	if selfIdentity == targetIdentity {
		return true, false
	}
	if targetIdentity == 0 {
		return false, true
	}
	//if selfIdentity == targetIdentity {
	//	return true, false
	//}
	if selfIdentity&targetIdentity&BaseIdentityType == 0 {
		return false, true
	}
	return true, false
}

func (logic *TypeManager) IsTargetIdentity(selfIdentity int, targetIdentity int, identity int) bool {
	isPartner, isEnemy := logic.JudgeIdentity(selfIdentity, targetIdentity)
	//fmt.Println("selectTarget", isPartner, isEnemy, selfIdentity, targetIdentity)
	if utils.IncludeIntByte(identity, int(PartnerTargetIdentity)) && !isPartner {
		return false
	}
	if utils.IncludeIntByte(identity, int(EnemyTargetIdentity)) && !isEnemy {
		return false
	}
	if utils.IncludeIntByte(identity, int(NeutralTargetIdentity)) && !isEnemy {
		return false
	}
	return true
}

func (logic *TypeManager) GetAbilityInstance(mapInstance cooperate.MapBase, data structure.Data) *cooperate.AbilityOwner {
	instance := logic.GetDetailCache(mapInstance, data)
	if instance == nil {
		return nil
	}
	ability := ReceiveAbilityProp(instance)
	if ability == nil {
		return nil
	}
	return ability.AbilityOwner
}

func (logic *TypeManager) GetSourceEffect(dataType structure.PublicDataType, key string, source cooperate.AbilitySource, define map[int]int) map[structure.PublicDataType]map[string]cooperate.AbilityEffect {
	empty := map[structure.PublicDataType]map[string]cooperate.AbilityEffect{}
	id := logic.Center.TargetIdMap[dataType][key]
	//fmt.Println("source", dataType, key, source, define, id)
	switch source {
	case model.LevelAbilitySource:
		if key == "" {
			break
		}
		switch dataType {
		case AccountType:
		case BuildType:
			//fmt.Println(id, dataType, key, define)
			empty[BuildType] = map[string]cooperate.AbilityEffect{key: logic.Center.BuildMap[id].Levels[define[0]].EffectSlice}
		case UnitType:
			if _, ok := logic.Center.UnitMap[id]; !ok {
				return empty
			}
			empty[UnitType] = map[string]cooperate.AbilityEffect{key: logic.Center.UnitMap[id].Levels[define[0]].EffectSlice}
			//fmt.Println(id, dataType, key, define, logic.Center.UnitMap[id].Levels[define[0]].EffectSlice)
		case ItemType:
			empty[ItemType] = map[string]cooperate.AbilityEffect{key: logic.Center.ItemMap[id].EffectSlice}
		}
	case model.ScienceAbilitySource:
		empty[dataType] = map[string]cooperate.AbilityEffect{key: model.NewEffect()}
		for targetId, value := range define {
			level := logic.ScienceMap[targetId].Levels[value-1]
			for dataType, pm := range level.TargetEffectSlice {
				if _, ok := empty[dataType]; !ok {
					empty[dataType] = map[string]cooperate.AbilityEffect{}
				}
				keyMap := empty[dataType]
				for id, effect := range pm {
					targetKey := logic.TargetKeyMap[dataType][id]
					if targetKey == key {
						keyMap[key] = effect.MergeTo(keyMap[key])
					}
				}
			}
		}

	case model.PowerAbilitySource:
		ee := model.NewEffect()
		for targetId, value := range define {
			level := logic.PowerMap[targetId].Levels[value]
			level.EffectSlice.MergeTo(ee)
		}
		empty[dataType] = map[string]cooperate.AbilityEffect{key: ee}
	case model.EquipAbilitySource:
		ee := model.NewEffect()
		for targetId, value := range define {
			level := logic.EquipMap[targetId].Levels[value]
			level.EffectSlice.MergeTo(ee)
		}
		empty[dataType] = map[string]cooperate.AbilityEffect{key: ee}
	case model.PropAbilitySource:
		ee := model.NewEffect()
		for targetId, value := range define {
			if value <= 0 {
				continue
			}
			prop := logic.PropMap[targetId]
			prop.EffectSlice.MergeTo(ee)
		}
		empty[dataType] = map[string]cooperate.AbilityEffect{key: ee}
	}
	return empty
}

func (logic *TypeManager) FillOwner(instance cooperate.PropsInstance, owner *cooperate.AbilityOwner) {
	//fmt.Println("fill", instance.BaseData())
	switch instance.GetDataType() {
	case AccountType:
		var accountData *model.User
		//_ = context.Get("user", &accountData)
		if accountData == nil {
			accountData = logic.GetAccount(utils.ToInt(instance.GetId()))
		}
		if accountData == nil {
			owner.ChangeSource(model.ScienceAbilitySource, map[int]int{})
			return
		}
		// 填充科技
		owner.ChangeSource(model.ScienceAbilitySource, accountData.Sciences)
	case BuildType:
		owner.ChangeSource(model.LevelAbilitySource, map[int]int{0: instance.ToInt(Level)})
	case UnitType:
		//debug.PrintStack()
		//fmt.Println(instance.GetDataType(), instance.GetId())
		var unitData *model.UserUnit
		//_ = context.Get("user_unit", &unitData)
		if unitData == nil {
			unitData = logic.GetUnit(utils.ToString(instance.GetId()))
		}
		owner.ChangeSource(model.LevelAbilitySource, map[int]int{0: instance.ToInt(Level)})
		if unitData == nil {
			return
		}
		//填充装备和道具
		owner.ChangeSource(model.PowerAbilitySource, unitData.Powers)
		equipData := make(map[int]int, len(unitData.Equips))
		for _, item := range unitData.Equips {
			if item == nil {
				continue
			}
			equipData[item.EquipId] = 1
		}
		owner.ChangeSource(model.EquipAbilitySource, equipData)
		propData := make(map[int]int, len(unitData.Props))
		for _, item := range unitData.Props {
			if item == nil {
				continue
			}
			propData[item.PropId] = item.Number
		}
		owner.ChangeSource(model.PropAbilitySource, propData)
		unitData.Level = instance.ToInt(Level)
	case ItemType:
		owner.ChangeSource(model.LevelAbilitySource, map[int]int{0: 0})
	}
}

func (logic *TypeManager) BaseEffect() cooperate.AbilityEffect {
	return model.NewEffect()
}

func (logic *TypeManager) DataRange(instance cooperate.PropsInstance) uint16 {
	r := uint16(0)
	key := instance.ToString(Key)
	id := logic.Center.TargetIdMap[instance.GetDataType()][key]
	switch instance.GetDataType() {
	case BuildType:
		build := logic.Center.BuildMap[id]
		if build != nil {
			r = build.Range
		}
	case NodeType:
		node := logic.Center.NodeMap[id]
		if node != nil {
			r = node.Range
		}
	case UnitType:
		unit := logic.Center.UnitMap[id]
		if unit != nil {
			r = unit.Range
		}
	case ItemType:
		item := logic.Center.ItemMap[id]
		if item != nil {
			r = item.Range
		}
	}
	return r
}
